<template>
  <div class="v-milestone-status">
    <div class="left">
      <div class="box">
        <div class="title">{{ $t("项目线") }}</div>
        <div
          class="content"
          @click="clearSelect()"
        >
          <div class="g-ai-c">
            <el-button
              class="g-ai-c"
              :disabled="disabled"
              @click="addProjectTheme"
            >
              <img
                src="statics/icons/app/add.svg"
                width="14px"
              />
              <span>{{ $t("添加") }}</span>
            </el-button>
            <el-button
              class="g-ai-c"
              :disabled="disabled || !selectedProjectThread"
              @click="deleteProjectTheme"
            >
              <img
                src="statics/icons/table/icondelete2.svg"
                width="14px"
              />
              <span>{{ $t("删除") }}</span>
            </el-button>
          </div>
          <div
            ref="projectThreadArea"
            class="list-area"
          >
            <div
              v-for="item in projectThreadList"
              :key="item.value"
              class="list-item"
              :class="{ selected: selectedProjectThread === item.value }"
              @dblclick.stop="handleProjectThreadDblClick(item)"
              @click="e => handleProjectThreadClick(item, e)"
            >
              <el-input
                v-if="projectThreadInEdit === item.value"
                v-model="projectThreadInEditName"
                v-focus
                @change="changeProjectThreadName"
              ></el-input>
              <span
                v-else
                class="g-pd-l-8 text"
              >
                {{ item.label }}
              </span>
            </div>
          </div>
        </div>
      </div>
      <div class="blank"></div>
      <div class="box">
        <div class="title">{{ $t("状态设置") }}</div>
        <div
          class="content"
          @click="clearSelect()"
        >
          <div class="g-ai-c">
            <el-button
              class="g-ai-c"
              :disabled="disabled || addStatusDisabled || !selectedProjectThread || statusMap.get(selectedProjectThread)?.disabled"
              @click="addStatus"
            >
              <img
                src="statics/icons/app/add.svg"
                width="14px"
              />
              <span>{{ $t("添加") }}</span>
            </el-button>
            <el-button
              class="g-ai-c"
              :disabled="disabled || !selectedStatus || statusMap.get(selectedProjectThread)?.disabled"
              @click="deleteStatus"
            >
              <img
                src="statics/icons/table/icondelete2.svg"
                width="14px"
              />
              <span>{{ $t("删除") }}</span>
            </el-button>
          </div>
          <div
            ref="statusArea"
            class="list-area"
          >
            <div
              v-for="item in statusList"
              :key="item.value"
              class="list-item"
              :class="{ selected: selectedStatus === item.value }"
              @dblclick.stop="handleStatusDblClick(item)"
              @click="e => handleStatusClick(item, e)"
            >
              <el-color-picker
                v-model="item.color"
                show-alpha
                @change="val => colorChange(item.value, val)"
              />
              <el-input
                v-if="statusInEdit === item.value"
                v-model="statusInEditName"
                v-focus
                @change="changeColorName"
              ></el-input>
              <span
                v-else
                class="g-pd-l-8 text"
              >
                {{ item.label }}
              </span>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="blank"></div>
    <div class="right">
      <div class="box">
        <div class="title">{{ $t("预览") }}</div>
        <div class="content">
          <div
            ref="pieChart"
            style="height: 100%"
          ></div>
        </div>
      </div>
    </div>
  </div>
</template>
<script lang="ts" setup>
import { ref, watch, onMounted, onBeforeUnmount, nextTick } from "vue";
import * as echarts from "echarts/core";
import { PieChart, PieSeriesOption } from "echarts/charts";
import { LabelLayout } from "echarts/features";
import { CanvasRenderer } from "echarts/renderers";
import { modelService } from "@/mdesign-lib/mdesign-app.umd.js";
import { rmi } from "@/util/IpcWindow/RMI";
import { StType } from "@/mdesign-lib/mdesign-app.umd.js";
import { MetaclassType } from "@/mdesign-lib/mdesign-app.umd.js";
import { PropertyKey } from "@/mdesign-lib/mdesign-app.umd.js";
import { archService } from "@/mdesign-lib/mdesign-app.umd.js";
import { ModelData } from "@/mdesign-lib/mdesign-app.umd.js";
import { NodeData } from "@/modules/model/project/IGraphNode";

interface SelectOption {
  label: string;
  value: string;
  icon?: string;
}

interface StatusOption extends SelectOption {
  color: string;
}

interface StatusItem {
  typeId: string;
  disabled: boolean;
  statusList: StatusOption[];
  selectedKey?: string;
}

const props = defineProps<{
  projectId: string;
  modelIds: string[];
  currentActualProjectMilestoneId?: string;
}>();

const emit = defineEmits<{
  (e: "stepValueChange", value: Record<string, string>, path: string[]): void;
}>();

echarts.use([PieChart, CanvasRenderer, LabelLayout]);

type EChartsOption = echarts.ComposeOption<PieSeriesOption>;

const option: EChartsOption = {
  series: [
    {
      name: "Access From",
      type: "pie",
      radius: "50%",
      selectedMode: "single",
      selectedOffset: 12,
      data: [],
      emphasis: {
        scale: false
      },
      label: {
        show: true,
        formatter(param: any) {
          return param.data.label;
        }
      },
      itemStyle: {
        borderColor: "rgba(0,0,0,0.45)",
        borderWidth: 0.5
      },
      labelLine: {
        lineStyle: {
          color: "rgba(0,0,0,0.45)",
          width: 0.5
        }
      }
    }
  ]
};

const projectThreadList = ref<SelectOption[]>([]);

const statusList = ref<StatusOption[]>([]);
const statusMap = new Map<string, StatusItem>();

const disabled = ref(false);
const selectedProjectThread = ref("");
const projectThreadInEdit = ref("");
const projectThreadInEditName = ref("");
const selectedStatus = ref("");
const statusInEdit = ref("");
const statusInEditName = ref("");
const addStatusDisabled = ref(false);

const pieChart = ref<HTMLElement>();

const statusArea = ref<HTMLElement | null>();
const projectThreadArea = ref<HTMLElement | null>();

let myChart: echarts.ECharts;

window.addEventListener("resize", chartResize);

onMounted(async () => {
  initChart();
  initData();
});

const initData = async () => {
  console.log("initData");
  statusMap.clear();
  clearSelect();
  isDisabled();
  await getProjectThemeList();
  const getStatusListQuene = projectThreadList.value.map(item => {
    return getStatusList(item.value);
  });
  await Promise.all(getStatusListQuene);
  await initSelectedStatus();
  selectedProjectThread.value = projectThreadList.value[0]?.value || "";
};

const initChart = () => {
  myChart = echarts.init(pieChart.value as HTMLElement);
  myChart.setOption(option);
  myChart.on("selectchanged", function (params: any) {
    const selected = params.selected as any[];
    if (selected.length > 0) {
      const index = selected[0].dataIndex[0] as number;
      selectedProjectThread.value = projectThreadList.value[index].value;
    }
  });
};

watch(() => props.modelIds, initData);

watch(
  [projectThreadList, statusList, selectedStatus],
  () => {
    const properties: Record<string, string> = {};
    console.log("fresh chart");
    const data = projectThreadList.value.map(item => {
      const currentStatus = statusMap.get(item.value);
      let color = "rgba(0, 0, 0, 0)";
      if (currentStatus) {
        const currentStatusList = currentStatus.statusList;
        const selectedKey = currentStatus.selectedKey || currentStatusList[0]?.value || "";
        const statusItem = currentStatusList.find(it => it.value === selectedKey);
        color = statusItem?.color || "rgba(0, 0, 0, 0)";
        if (statusItem) {
          properties[item.value] = statusItem.value;
        }
      }
      return {
        value: 100,
        name: item.value,
        label: item.label,
        itemStyle: { color }
      };
    });
    myChart.setOption({
      series: { data }
    });
    emit("stepValueChange", properties, ["properties"]);
  },
  { deep: true }
);

watch(selectedProjectThread, async id => {
  setStatusList();
  const currentStatus = statusMap.get(selectedProjectThread.value);
  selectedStatus.value = currentStatus?.selectedKey || statusList.value[0]?.value || "";
  myChart.dispatchAction({
    type: "select",
    name: id
  });
});

onBeforeUnmount(() => {
  myChart && myChart.dispose();
  window.removeEventListener("resize", chartResize);
});

function chartResize() {
  myChart && myChart.resize();
}

const initSelectedStatus = async () => {
  const currentActualProjectMilestoneId = props.currentActualProjectMilestoneId;
  if (currentActualProjectMilestoneId) {
    const modelInfo = await modelService.getModelData(props.projectId, currentActualProjectMilestoneId);
    const projectStatus = modelInfo.showAttribute.extraAttribute?.projectStatus;
    if (projectStatus) {
      projectStatus.forEach(item => {
        const projectThreadId = item.propertyId;
        const enumerationLiteralId = item.enumerationLiteralId;
        const currentStatus = statusMap.get(projectThreadId);
        if (currentStatus) {
          currentStatus.selectedKey = enumerationLiteralId;
        }
      });
    }
  }
};

const handleProjectThreadClick = (item, event: Event) => {
  if (selectedProjectThread.value === item.value) {
    event.stopPropagation();
  }
  selectedProjectThread.value = item.value;
};

const handleProjectThreadDblClick = item => {
  projectThreadInEdit.value = item.value;
  projectThreadInEditName.value = item.label;
};

const handleStatusClick = (item, event: Event) => {
  if (selectedStatus.value === item.value) {
    event.stopPropagation();
  }
  const currentStatus = statusMap.get(selectedProjectThread.value);
  selectedStatus.value = currentStatus!.selectedKey = item.value;
};

const handleStatusDblClick = item => {
  statusInEdit.value = item.value;
  statusInEditName.value = item.label;
};

const clearSelect = () => {
  statusInEdit.value = "";
  projectThreadInEdit.value = "";
  projectThreadInEditName.value = "";
  statusInEditName.value = "";
};

const isDisabled = async () => {
  const quene: Promise<boolean>[] = [];
  props.modelIds.forEach(id => {
    quene.push(rmi.invoke("app.modelService.isModelDisabled", [id, props.projectId]).then(data => data as boolean));
  });
  disabled.value = await Promise.all(quene).then(res => res.some(item => item));
};

const getProjectThemeList = async () => {
  const quene: Promise<NodeData[]>[] = [];
  props.modelIds.forEach(id => {
    quene.push(modelService.getChildNodeDatas(props.projectId, id));
  });
  const nodes = await Promise.all(quene).then(res =>
    res.reduce((previousValue, currentValue) => {
      return previousValue.concat(currentValue);
    }, [])
  );
  projectThreadList.value = nodes
    .filter(node => node.baseSt === ("UAF::Projects::Structure::ProjectTheme" as StType))
    .map(node => ({ value: node.id, label: node.name }));
};

const addProjectTheme = async () => {
  const res = await rmi
    .invoke("app.modelService.addModel", [
      props.projectId,
      props.modelIds[0],
      MetaclassType.Property,
      ["UAF::Projects::Structure::ProjectTheme"]
    ])
    .then(data => data as NodeData[]);
  await getProjectThemeList();
  selectedProjectThread.value = res[0].id;
  scrollToBottom(projectThreadArea.value);
};

const deleteProjectTheme = async () => {
  await modelService.removeModel(props.projectId, [selectedProjectThread.value]);
  await getProjectThemeList();
  selectedProjectThread.value = projectThreadList.value[projectThreadList.value.length - 1]?.value || "";
};

const changeProjectThreadName = async (val: string) => {
  await modelService.renameNode(props.projectId, selectedProjectThread.value, val).catch(err => console.log(err));
  getProjectThemeList();
};

const getStatusList = async (id?: string, reQueryStatusList = false) => {
  if (id) {
    const statusData = statusMap.get(id);
    let typeId = "";
    if (statusData) {
      typeId = statusData.typeId;
    } else {
      reQueryStatusList = true;
    }

    if (!reQueryStatusList) return;

    if (!typeId) {
      const typePropertyRow = await modelService
        .getModelPropertiesByKeys(props.projectId, id, [PropertyKey.TypedElement_type])
        .then(data => data[0]);
      const typeValue = typePropertyRow.value as ModelData;
      typeId = typeValue?.id;
    }

    if (typeId) {
      const currentStatusList = await modelService.queryEnumerationLiterals(props.projectId, typeId).then(list => {
        return list.map(item => {
          const color = item.alpha == null ? null : `rgba(${item.r},${item.g},${item.b},${item.alpha})`;
          return {
            label: item.label,
            value: item.value,
            color
          };
        });
      });

      // console.log('currentStatusList', currentStatusList);
      const statusDiasbled = statusData
        ? statusData.disabled
        : await rmi.invoke("app.modelService.isModelDisabled", [typeId, props.projectId]).then(data => data as boolean);
      statusMap.set(id, {
        statusList: currentStatusList,
        typeId,
        disabled: statusDiasbled,
        selectedKey: statusData?.selectedKey || ""
      });
    }
  }
};

const setStatusList = () => {
  const currentStatus = statusMap.get(selectedProjectThread.value);
  statusList.value = currentStatus?.statusList || [];
};

const addStatus = async () => {
  addStatusDisabled.value = true;
  const statusId = statusMap.get(selectedProjectThread.value)?.typeId;
  await archService.addMilestoneStatus(props.projectId, selectedProjectThread.value, statusId);
  await getStatusList(selectedProjectThread.value, true);
  setStatusList();
  const currentStatus = statusMap.get(selectedProjectThread.value);
  selectedStatus.value = currentStatus!.selectedKey = statusList.value[statusList.value.length - 1].value;
  addStatusDisabled.value = false;
  scrollToBottom(statusArea.value);
};

const deleteStatus = async () => {
  await modelService.removeModel(props.projectId, [selectedStatus.value]);
  await getStatusList(selectedProjectThread.value, true);
  setStatusList();
  const currentStatus = statusMap.get(selectedProjectThread.value);
  selectedStatus.value = currentStatus!.selectedKey = statusList.value[statusList.value.length - 1]?.value || "";
};

const changeColorName = async (val: string) => {
  await modelService.renameNode(props.projectId, selectedStatus.value, val).catch(err => console.log(err));
  await getStatusList(selectedProjectThread.value, true);
  setStatusList();
};

const colorChange = (colorId: string, val: string | null) => {
  if (val) {
    const nums = val.match(/(\d+)/g)?.map(item => parseInt(item)) as number[];
    archService.updateStatusColor(props.projectId, colorId, nums[0], nums[1], nums[2], nums[3]);
  } else {
    archService.updateStatusColor(props.projectId, colorId, null, null, null, null);
  }
};

const scrollToBottom = (element?: HTMLElement | null) => {
  nextTick(() => {
    element && element.scrollTo({ top: element.scrollHeight });
  });
};
</script>
<style lang="scss">
.v-milestone-status {
  height: 100%;
  display: flex;
  .left {
    flex: 1;
    display: flex;
    flex-direction: column;
  }
  .right {
    flex: 3;
    display: flex;
  }
  .blank {
    height: 8px;
    width: 9px;
  }
  .box {
    flex: 1;
    border: 1px solid #e0e0e0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    .title {
      height: 24px;
      background: #e1e4fd;
      line-height: 24px;
      padding-left: 8px;
      font-weight: 500;
      color: #000000;
    }
    .content {
      flex: 1;
      background: #f8f9ff;
      border-top: 1px solid #e0e0e0;
      padding: 8px;
      overflow: hidden;
      display: flex;
      flex-direction: column;
      button {
        transition: unset;
        height: 32px;
        padding: 0 8px;
        border-radius: 0px;
        & + button {
          margin-left: 8px;
        }
        &[disabled] {
          img {
            opacity: 0.25;
          }
        }
        span {
          line-height: 16px;
        }
        img {
          width: 14px;
          margin-right: 5px;
        }
      }
      .list-area {
        margin-top: 8px;
        overflow: auto;
        flex: 1;
        .list-item {
          height: 24px;
          border: 1px solid #e0e0e0;
          border-bottom: 0;
          display: flex;
          align-items: center;
          background-color: #fff;

          &:last-of-type {
            border-bottom: 1px solid #e0e0e0;
          }
          &.selected {
            background-color: var(--background-color-active);
            color: #fff;
          }
          .text {
            font-family: arial;
          }
          .el-color-picker {
            height: 100%;
            width: 31px;
            border-right: 1px solid #e0e0e0;
            display: flex;
            align-items: center;
            justify-content: center;
            .el-color-picker__trigger {
              height: 18px;
              width: 18px;
              border-radius: 2px;
              padding: 0;
              border: 0;
              overflow: hidden;
              .el-color-picker__color {
                border: 0;
              }
              .el-icon {
                display: none;
              }
            }
          }

          .el-input {
            height: 100%;
            flex: 1;
            .el-input__wrapper {
              box-shadow: none;
              padding: 0 8px;
              height: 100%;
              input {
                height: 100%;
              }
            }
          }
        }
      }
    }
  }
}
</style>
